home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #2 / Ham Radio 2000 - Volume 2.iso / HAMV2 / TCP_IP / TNOS230S / MAIN.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-09-14  |  59.8 KB  |  2,697 lines

  1. /* Main-level network program:
  2.  * initialization
  3.  * keyboard processing
  4.  * generic user commands
  5.  *
  6.  * Copyright 1991 Phil Karn, KA9Q
  7.  * Mods by KO4KS
  8.  */
  9. #include "global.h"
  10. #include <fcntl.h>
  11. #include "ctype.h"
  12. #include "commands.h"
  13. #if defined(MSDOS)
  14. #include <conio.h>
  15. #else
  16. #include <time.h>
  17. #endif
  18. #ifdef UNIX
  19. #include <sys/stat.h>
  20. #ifdef BSD
  21. #include <signal.h>
  22. #endif
  23. #endif
  24. #include <stdarg.h>
  25. #include "mbuf.h"
  26. #include "timer.h"
  27. #include "proc.h"
  28. #include "iface.h"
  29. #include "udp.h"
  30. #include "netrom.h"
  31. #include "ftpcli.h"
  32. #include "tty.h"
  33. #include "usock.h"
  34. #include "daemon.h"
  35. #include "devparam.h"
  36. #include "domain.h"
  37. #include "mailbox.h"
  38. #include "files.h"
  39. #include "main.h"
  40. #include "remote.h"
  41. #include "trace.h"
  42. #ifdef fprintf
  43. #undef fprintf
  44. #endif
  45. #include "mailutil.h"
  46. #include "smtp.h"
  47. #include "assoc.h"
  48. #ifdef SQL
  49. #include "sql.h"
  50. #endif
  51. #ifdef CATALOG
  52. #include "catalog.h"
  53. #endif
  54. #include "asy.h"
  55. #ifdef MSDOS
  56. #include "n8250.h"
  57. #else
  58. #include "unixasy.h"
  59. #endif
  60. #include "slip.h"
  61. #include "nrs.h"
  62.  
  63. #if !defined(_lint)
  64. static char rcsid[] OPTIONAL = "$Id: main.c,v 1.55 1997/09/14 14:37:46 root Exp root $";
  65. #endif
  66.  
  67.  
  68. #ifdef MSDOS
  69. #undef  FA_DIREC
  70. #define FA_DIREC 0x10
  71. #endif
  72.  
  73. #ifdef SCREENSAVER
  74. extern int32 LastIO;
  75. #endif
  76.  
  77. #ifdef AX25
  78. void reset_all_ax25 (void);
  79. #endif
  80.  
  81. static char symname[] = "$Name: Release2_30 $";
  82.  
  83. extern int Warnings;
  84. static int CrashProtect = 0;
  85.  
  86.  
  87. #ifdef LOG_GMT_TZ
  88. #define TZTIME(x) asctime(gmtime(x))
  89. #else
  90. #define TZTIME(x) ctime(x)
  91. #endif
  92.  
  93. #if defined(__bsdi__) || defined(__FreeBSD__)
  94. extern char *tzname[2];
  95. #endif
  96.  
  97. #ifdef BROWSER
  98. static int UpdateTimeout = 30;
  99. #endif
  100.  
  101. extern int getcolor (char *color);
  102. extern int SYSback, SYSfore;
  103.  
  104. #ifdef RLINE
  105. extern void ReadFwdBbs (void);
  106. #endif
  107. extern struct cmds Cmds[], Attab[];
  108. #ifdef MSDOS
  109. char vgaDesired = 0;
  110. #endif
  111. extern unsigned char SCREENlength, SCREENwidth;
  112. extern void display_map (void);
  113.  
  114. extern short NextCmd;
  115. extern struct session *ScreenOwner;    /* Session currently displayed */
  116.  
  117. #if    (!defined(MSDOS) || defined(ESCAPE))    /* PC uses F-10 key always */
  118. static char Escape = 0x1d;    /* default escape character is ^] */
  119. #endif
  120.  
  121. char NoRead[] = "Can't read %s: %s\n";
  122. char Badhost[] = "Host '%s' unknown\n";
  123. char Badinterface[] = "Interface \"%s\" unknown\n";
  124. char Existingiface[] = "Interface %s already exists\n";
  125. char Nospace[] = "No space!!\n";/* Generic malloc fail message */
  126. char readmeFile[] = "features.new";
  127. extern char Tnosversion[];
  128. char Nosversion[] = "KA9Q NOS version %s\n%s";
  129.  
  130. static char MPRUNNINGerr[] = "\007*** Cannot resolve hostnames in the startup file!\n"
  131.     "*** Try using the ip address (xx.xx.xx.xx) instead\n***\n"
  132.     "*** The following command could NOT be completed:\n"
  133.     "***     %s***\n\n";
  134.  
  135. #ifdef UNIX
  136. static char LockName[] = "tnos.lock";
  137. extern char const *LOCKDIR;
  138. #endif
  139.  
  140. char Compiled[] = "Compiled"
  141. #ifdef __GNUC__
  142.     " with "
  143. #ifdef MSDOS
  144.     "DJGPP "
  145. #else
  146.     "GCC "
  147. #endif
  148.      __VERSION__
  149. #endif
  150.     " on " __DATE__ " at " __TIME__ "\n";
  151.  
  152. static char Prompt[] = "Net";
  153. char Noperm[] = "Permission denied.\n";
  154. char Nosock[] = "Can't create socket\n";
  155. static char FromSysop[] = "*** Msg from SYSOP: %s\n";
  156. char SysMessage[] = "System message";
  157. char *Hostname = NULLCHAR;
  158. char *Motd = NULLCHAR;        /* Message Of The Day */
  159. extern int Attended;
  160. int ThirdParty = TRUE;        /* Allows 3rd party mail by default */
  161. int main_exit = FALSE;        /* from main program (flag) */
  162. int Mprunning = -1;        /* flag for other parts (domain) to signal
  163.                  * that we are fully configured running. */
  164. int Mprunning_err;
  165. struct proc *Cmdpp;
  166. #ifndef UNIX
  167. struct proc *Display;
  168. #endif
  169.  
  170. #ifdef    LZW
  171. int Lzwmode = LZWCOMPACT;
  172. int16 Lzwbits = LZWBITS;
  173. #endif
  174.  
  175. #ifdef SCRIPTING
  176. extern AarrayPtr SetVariables;
  177. #endif
  178.  
  179. #ifdef MBFWD
  180. extern int FWDmode;
  181. #endif
  182.  
  183. #ifdef TRACE
  184. int Tracesession = 1;
  185. struct session *Trace = NULLSESSION;
  186. #endif
  187.  
  188. #ifdef SOUNDS
  189. int dosounddefine (int argc, char *argv[], void *p);
  190. #endif
  191.  
  192. #ifdef AXIP
  193. extern uint32 *axipaddr;
  194. extern int AXIPlinks;
  195. #endif
  196.  
  197. extern int mbxMaxUsers;
  198.  
  199. static char PromptType;
  200. static char *Customprompt;
  201.  
  202. #if defined(ALLCMD) && !defined(UNIX)
  203. static char *DumpAddr = NULL;    /* Memory dump pointer */
  204. #endif
  205.  
  206. FILE *Logfp;
  207. time_t StartTime;        /* Time that NOS was started */
  208. static int Verbose;
  209. char *firstMsg;
  210. int Numrows, Numcols;        /* screen size at startup - WG7J */
  211. struct hist *Histry;        /* command recall stuff */
  212. static int Histrysize = 0;
  213. static int Maxhistory = 10;
  214.  
  215. #ifdef TNOS_68K
  216. extern int Initroot;
  217. extern int TNOS_68KAlarm;
  218. extern short UseCurses;
  219. #endif
  220.  
  221. extern int INStatline;
  222. extern int BLOCKStatline;
  223.  
  224. #ifdef UNIX
  225. static char **origargv;
  226.  
  227. #ifdef SETPSINFO
  228. static char *LastArgv = NULL;          /* end of argv */
  229. extern void fix_env (void);
  230. extern int tnos_putenv (const char *envstr);
  231. #endif
  232. #endif
  233.  
  234. int chksession (struct session * sp);
  235. extern void usercvt (void);
  236. extern void setscreens (int back, int fore, int clr);
  237.  
  238. #if defined(ALLCMD) && !defined(UNIX)
  239. static void ctohex (char *buf, int16 c);
  240. static void fmtline (uint32 addr, char *buf, int16 len);
  241. #endif
  242.  
  243. #ifdef MSDOS
  244. extern void DOSinit (void);
  245. extern void DOSterm (void);
  246. #endif
  247. extern void statLineToggle (int clearmarquee);
  248. extern void statlog (const char *buf);
  249. static void logcmd (char *);
  250. static void freehistory (void);
  251. static int _dowriteall (char *str);
  252.  
  253. void variable_expansion (struct mbuf ** bp);
  254.  
  255. #ifdef UNIX
  256. #define VALIDOPTS "A:a:B:D:d:Ef:g:k:l:mno:P:r:S:s:T:tU:Vv?"
  257. #endif
  258. #ifdef MSDOS
  259. #define VALIDOPTS "A:a:B:D:d:Eef:g:h:k:mno:P:r:s:U:Vv?"
  260. #endif
  261. #ifdef TNOS68K
  262. #define VALIDOPTS "A:a:B:cD:d:Ef:g:k:mno:P:r:s:U:Vv?"
  263. #endif
  264.  
  265.  
  266. void
  267. netPrompt ()
  268. {
  269. char const *str;
  270.  
  271.     switch (PromptType) {
  272.         case 3:
  273.             str = Customprompt;
  274.             break;
  275.         case 2:
  276.             str = Command->curdirs->dir;
  277.             break;
  278.         case 1:
  279.             if (Hostname) {
  280.                 str = Hostname;
  281.                 break;
  282.             }    /* else, fall through */
  283.         default:
  284.             str = Prompt;
  285.     }
  286.     tprintf ("%s> ", str);
  287.     usflush (Curproc->output);
  288. }
  289.  
  290.  
  291. int
  292. main (int argc, char **argv, char **envp)
  293. {
  294. char *inbuff, *intmp;
  295. FILE *fp;
  296. struct daemon *tp;
  297. struct mbuf *bp;
  298. int i;
  299. int c;
  300. int did_init;
  301. #ifdef UNIX
  302. int setlockdir = 0;
  303. int no_itimer = 0;
  304. const char *trace_sm = 0;
  305. const char *def_sm = 0;
  306. static int oops = 0;
  307. #else
  308. long hinit = 102400;
  309. struct text_info ti;
  310. #endif
  311. struct cur_dirs dirs;
  312. int32 cmdcounter = 0;
  313.  
  314. #ifdef UNIX
  315.     if (oops++) {
  316.         iostop ();
  317.         fprintf (stderr, "NOS PANIC: NOS main re-entered.\n");
  318.         (void) fflush (stderr);
  319.         (void) fflush (stdout);
  320.         (void) kill (getpid (), 11);
  321.     }
  322.     origargv = argv;
  323. #ifdef SETPSINFO
  324.     while (*envp)    {
  325.         (void) tnos_putenv (*envp);
  326.         envp++;
  327.     }
  328.     LastArgv = envp[-1] + strlen(envp[-1]);
  329.  
  330.     fix_env ();
  331. #endif
  332. #endif
  333.     StartTime = time ((time_t *)0);    /* NOS Start_Up time */
  334. #ifdef MSDOS
  335.     (void)
  336. #endif
  337.     SRANDOM ((long)((((unsigned int)getpid ()) << 16) ^ (unsigned long) StartTime));
  338.  
  339. #ifdef MSDOS
  340.     /* Borland's library calls int10. Some vga mode utilities do not
  341.      * report the screen sizes correctly into the internal _video structure.
  342.      * This can cause the screen size to be faulty in the gettextinfo call.
  343.      * Instead, read the BIOS data area to get the correct screen info,
  344.      * and update the _video structure for later calls to
  345.      * gettextinfo(), clrscr(), etc... - WG7J
  346.      *
  347.      * If this doesn't work, you can now overwrite the values with
  348.      * the -r and -c command line options - WG7J
  349.      */
  350.     gettextinfo (&ti);
  351.     Numcols = ti.screenwidth;
  352.     Numrows = ti.screenheight;
  353.  
  354.     if (Numrows == 1)
  355.         Numrows = 25;
  356. #endif
  357.     list_filenames (1);
  358.     did_init = 0;
  359.     while ((c = getopt (argc, argv, VALIDOPTS)) != EOF) {
  360.         switch (c) {
  361.             case '?':    /* only display version info */
  362.                 printf (Nosversion, Version, Compiled);
  363.                 puts (Version2);
  364.                 exit (0);
  365.                 break;
  366.  
  367.             case 'A':    /* max number of SLIP/AX25 devices allowed */
  368.                 SLIP_MAX = atoi (optarg);
  369.                 break;
  370.  
  371.             case 'B':    /* max number of BBS processes allowed */
  372.                 NUMMBX = atoi (optarg);
  373.                 break;
  374.  
  375. #ifdef SCRIPTING
  376.             case 'D':    /* define new environment variables */
  377.                 inbuff = strchr (optarg, '=');
  378.                 if (inbuff)
  379.                     *inbuff++ = 0;
  380.                 else
  381.                     inbuff = optarg;
  382.                 (void) assoc_addstr (&SetVariables, optarg, inbuff, 1);
  383.                 break;
  384.  
  385.             case 'E':    /* import environment variables */
  386.                 for (i = 0; envp[i] && *envp[i]; i++) {
  387.                     intmp = strdup (envp[i]);
  388.                     inbuff = strchr (intmp, '=');
  389.                     if (inbuff) {
  390.                         *inbuff++ = 0;
  391.                         (void) assoc_addstr (&SetVariables, intmp, inbuff, 1);
  392.                     }
  393.                     free (intmp);
  394.                 }
  395.                 break;
  396. #endif
  397.  
  398.             case 'P':    /* max number of ASY port devices allowed */
  399.                 ASY_MAX = atoi (optarg);
  400.                 break;
  401.  
  402. #ifdef UNIX
  403.             case 'S':
  404.                 if (sm_lookup (optarg, 0))
  405.                     def_sm = optarg;
  406.                 else
  407.                     printf ("No session manager \"%s\", using default\n", optarg);
  408.                 break;
  409.  
  410.             case 'T':
  411.                 if (sm_lookup (optarg, 0))
  412.                     trace_sm = optarg;
  413.                 else
  414.                     printf ("Session manager for trace not found, using default\n");
  415.                 break;
  416. #endif
  417.  
  418. #ifdef BROWSER
  419.             case 'U':    /* Auto update timeout */
  420.                 UpdateTimeout = atoi (optarg);
  421.                 break;
  422. #endif
  423.  
  424.             case 'V':
  425.                 Verbose = 2;
  426.                 break;
  427.  
  428. #ifdef AXIP
  429.             case 'a':    /* number of axip interfaces */
  430.                 AXIPlinks = atoi (optarg);
  431.                 break;
  432. #endif
  433.  
  434. #ifdef TNOS_68K
  435.             case 'c':    /* curses mode */
  436.                 UseCurses = 1;
  437.                 break;
  438. #endif
  439.  
  440.             case 'd':    /* Root directory for various files */
  441.                 initroot (optarg);
  442.                 break;
  443.  
  444. #ifdef MSDOS
  445.             case 'e':    /* EGA/VGA 43/50 mode desired */
  446.                 vgaDesired = 1;
  447.                 break;
  448. #endif
  449.  
  450.             case 'f':    /* read a filename config file */
  451.                 assign_filenames (optarg, 1);
  452.                 did_init = 1;
  453.                 break;
  454.  
  455.             case 'g':    /* foreground color */
  456.                 i = getcolor (optarg);
  457.                 if (i != -1)
  458.                     SYSfore = i;
  459.                 break;
  460.  
  461. #ifdef MSDOS
  462.             case 'h':    /* Heap initialization */
  463.                 hinit = atol(optarg);
  464.                 break;
  465. #endif
  466.  
  467.             case 'k':    /* background color */
  468.                 i = getcolor (optarg);
  469. #ifdef MSDOS
  470.                 i += 10;
  471. #endif
  472.                 if (i != -1)
  473.                     SYSback = i;
  474.                 break;
  475.  
  476. #ifdef UNIX
  477.             case 'l':    /* set LOCKDIR path */
  478.                 findUnixLockdir(optarg);
  479.                 setlockdir = 1;
  480.                 break;
  481. #endif
  482.             case 'm':    /* only display TNOS MAP info */
  483.                 display_map ();
  484.                 exit (0);
  485.                 break;
  486.  
  487. #ifdef TRACE
  488.             case 'n':    /* No session for tracing */
  489.                 Tracesession = 0;
  490.                 break;
  491. #endif
  492.  
  493.             case 'o':    /* override number of interactive sessions */
  494.                 Nsessions = (unsigned) atoi (optarg);
  495.                 if (Nsessions < 5)
  496.                     Nsessions = 5;    /* but not less than 5 */
  497.                 break;
  498.  
  499. #ifdef NETROM
  500.             case 'r':    /* number of netrom open circuits */
  501.                 NR4MAXCIRC = atoi (optarg);
  502.                 break;
  503. #endif
  504.  
  505.             case 's':    /* Number of sockets */
  506.                 Nusock = atoi (optarg);
  507.                 break;
  508.  
  509. #ifdef UNIX
  510.             case 't':
  511.                 no_itimer = 1;    /* for debugging */
  512.                 break;
  513. #endif
  514.  
  515.             case 'v':
  516.                 Verbose = 1;
  517.                 break;
  518.  
  519.             default:
  520.                 break;
  521.         }
  522.     }
  523. #ifdef UNIX
  524.     if (!setlockdir)
  525.         findUnixLockdir (NULLCHAR);
  526.     {
  527.         char *rp = mallocw (sizeof (rootdir) + 2 + sizeof (LockName));
  528.         sprintf (rp, "%s/%s", rootdir, LockName);
  529.         if (Unixlockfile (rp, 0, LockName, 1) == -1)    {
  530.             printf ("Cannot start TNOS! Lockfile conflict!\n");
  531.             (void) fflush (stdout);
  532.             (void) sleep (5);
  533.             exit (1);
  534.         }
  535.         free (rp);
  536.     }
  537. #endif
  538.     if (SLIP_MAX > ASY_MAX)
  539.         ASY_MAX = SLIP_MAX;
  540.  
  541.     Asy = (struct asy *) calloc ((unsigned) ASY_MAX, sizeof (struct asy));
  542.     Slip = (struct slip *) calloc ((unsigned) SLIP_MAX, sizeof (struct slip));
  543. #ifdef TIPMAIL
  544.     Tipsuspended = (struct suspended *) calloc ((unsigned) ASY_MAX, sizeof (struct suspended));
  545. #endif
  546. #if defined(NETROM) && defined(NRS)
  547.     Nrs = (struct nrs *) calloc ((unsigned) ASY_MAX, sizeof (struct nrs));
  548. #endif
  549. #ifdef AXIP
  550.     axipaddr = calloc ((unsigned) AXIPlinks, sizeof (int32));
  551. #endif
  552.     Mbox = (struct mbx **) calloc ((unsigned) NUMMBX, sizeof (struct mbx *));
  553.  
  554.     mbxMaxUsers = NUMMBX;
  555. #ifdef MBFWD
  556.     subchannels = (struct subchan *) calloc ((unsigned) NUMMBX, sizeof (struct subchan));
  557.  
  558. #endif
  559. #ifdef NETROM
  560.     Nr4circuits = calloc ((unsigned) NR4MAXCIRC, sizeof (struct nr4circp));
  561.  
  562. #endif
  563.  
  564. #if defined(MSDOS)
  565.     DOSinit ();
  566. #endif
  567. #ifdef TNOS_68K
  568.     if (!Initroot)
  569.         initroot ("/dd/nos");
  570.     oskinit ();
  571. #ifdef TRACE
  572.     Tracesession = UseCurses;    /* no session trace if dumb terminal mode */
  573. #endif
  574. #endif
  575.     intmp = firstMsg;    /* we won't report an error here, if it occurs */
  576.     firstMsg = (char *) 0;
  577.     if (!did_init)
  578. #ifdef UNIX
  579.         assign_filenames (".nosrc", 1);
  580. #else
  581.         assign_filenames ("config.nos", 0);    /* automatically look for users config */
  582. #endif
  583.     if (firstMsg)
  584.         free (firstMsg);
  585.     firstMsg = intmp;
  586.     kinit ();
  587.     ipinit ();
  588. #ifdef UNIX
  589.     ioinit (no_itimer);
  590. #else
  591. #ifdef MSDOS
  592.     ioinit (hinit);
  593. #endif
  594. #endif
  595. #ifdef SQL
  596.     sql_init ();
  597. #endif
  598.     list_filenames (0);
  599. #ifdef MAILBOX
  600.     {
  601.         char tmpbuf[128];
  602.  
  603.         sprintf (tmpbuf, "%s/control", Mailspool);
  604.         (void) mkdir (tmpbuf, 0777);
  605.         sprintf (tmpbuf, "%s/users", Mailspool);
  606.         (void) mkdir (tmpbuf, 0777);
  607.     }
  608. #endif
  609. #ifdef AX25
  610.     memcpy (Mycall, NOCALL, AXALEN);
  611.     memcpy (AXuser, NOCALL, AXALEN);
  612. #endif
  613.     sockinit ();
  614.     Cmdpp = mainproc ("cmdintrp");
  615.  
  616.     Sessions = (struct session *) callocw (Nsessions, sizeof (struct session));
  617.  
  618.     for (i = 0; (unsigned) i < Nsessions; i++)
  619.         Sessions[i].index = i;
  620.  
  621. #ifdef TRACE
  622.     if (Tracesession)
  623. #ifdef UNIX
  624.     {
  625.         if (!trace_sm)
  626.             trace_sm = Trace_sessmgr;
  627.         Trace = sm_newsession (trace_sm, NULLCHAR, TRACESESSION, 0);
  628.     }
  629. #else
  630.         Trace = newsession (NULLCHAR, TRACESESSION, 0);
  631. #endif
  632. #endif
  633. #ifdef UNIX
  634.     if (!def_sm)
  635.         def_sm = Command_sessmgr;
  636.     ScreenOwner = Command = Lastcurr = sm_newsession (def_sm, NULLCHAR, COMMAND, 0);
  637. #else
  638.     ScreenOwner = Command = Lastcurr = newsession (NULLCHAR, COMMAND, 0);    /*"command int" not needed*/
  639. #endif
  640.     /* Flow mode is set AFTER we've read the autoexec file !
  641.      * this keeps systems from locking up if the reboot is unattended - WG7J
  642.      */
  643. #ifndef UNIX
  644.     Display = newproc ("display", 1024, display, 0, NULLCHAR, NULL, 0);
  645. #endif
  646.     setscreens (0, 0, 1);
  647.     if (firstMsg) {
  648.         tputs (firstMsg);
  649.         free (firstMsg);
  650.     }
  651.     tputs (Tnosversion);
  652.     tputs (Version2);
  653.     tputs ("Copyright 1991 by Phil Karn (KA9Q), Brian A. Lantz (KO4KS) and contributors.\n");
  654. #ifdef MSDOS
  655.     (void) _get_dos_version (1);
  656.     tprintf ("Running under %s - Version %d.%d\n", _os_flavor, _osmajor, _osminor);
  657. #endif
  658. #ifdef RLINE
  659.     ReadFwdBbs ();
  660. #endif
  661. #ifdef CATALOG
  662.     /* this serves two purposes. First, it will error if file not found
  663.        NOW rather than later. Second, it makes the OWNER of the open file
  664.        be the Command Session. If this wasn't done (and a user process
  665.        opened the file later) then the file is closed when the process
  666.        dies, which confuses TNOS totally!
  667.      */
  668.     switch (catalog_check ()) {
  669.         case -1:
  670.             tputs ("\nImproperly formatted etc/catalog.cat file!!\nIt looks corrupted. Unless you fix this, a crash is probable!\n\n\007");
  671.             break;
  672.         case 1:
  673.             tputs ("\nVersion of the etc/catalog.cat file does NOT match this executable!\nA crash is possible!\n\n\007");
  674.             break;
  675.         case 0:    /* nothing to do, it looks fine */
  676.         default:
  677.             break;
  678.     }
  679. #endif
  680.  
  681. #ifdef SOUNDS            /* pre-define the 'chat' sound */
  682.     {
  683.         char const *myargv[4];
  684.  
  685.         myargv[1] = "chat";
  686.         myargv[2] = "";
  687.         myargv[3] = "used to indicate an incoming chat session";
  688.         (void) dosounddefine (4, (char **) myargv, (void *) 0);
  689.     }
  690. #endif
  691.  
  692. #ifdef USERLOG
  693.     /* a special sanity check, in case TNOS dies in the midst of
  694.        updating the users.dat file */
  695.     {
  696.         long dat, bak;
  697.         char *tmpcp;
  698.  
  699.         tmpcp = strdup (UDefaults);
  700.         dat = fsize (tmpcp);
  701.         free (tmpcp);
  702.         tmpcp = strdup (UDefbak);
  703.         bak = fsize (tmpcp);
  704.         free (tmpcp);
  705.         if (bak > dat && (bak - dat) > 80L) {
  706.             unlink (UDefaults);
  707.             (void) rename (UDefbak, UDefaults);
  708.         }
  709.     }
  710. #endif
  711.  
  712.     rflush ();
  713.  
  714. #ifdef UNIX
  715.     SCREENlength = uchar(Numrows);
  716.     SCREENwidth = uchar(Numcols);
  717. #endif
  718.  
  719.     usercvt ();
  720.     /* Start background Daemons */
  721.     for (tp = Daemons;; tp++) {
  722.         if (tp->name == NULLCHAR)
  723.             break;
  724.         (void) newproc (tp->name, tp->stksize, tp->fp, 0, NULLCHAR, NULL, 0);
  725.     }
  726.  
  727.     (void) init_dirs (&dirs);
  728.     Command->curdirs = &dirs;
  729.  
  730.     Mprunning = 0;
  731.  
  732.     if (!access (readmeFile, 4)) {
  733.         int row;
  734.         char *args[2];
  735.  
  736.         args[1] = readmeFile;
  737.         tprintf ("\nWould you like to view the '%s' file, containing information\non the new features for this version of TNOS?\n", readmeFile);
  738.         Command->ttystate.edit = Command->ttystate.echo = 0;
  739.         row = keywait ("Yes or No [y/n]? ", 0);
  740.         Command->ttystate.edit = Command->ttystate.echo = 1;
  741.         if (row == 'Y' || row == 'y')
  742.             (void) doview (2, args, 0);
  743.         tputc ('\n');
  744.     }
  745.     if (optind < argc) {
  746.         /* Read startup file named on command line */
  747.         if ((fp = fopen (argv[optind], READ_TEXT)) == NULLFILE)
  748.             tprintf (NoRead, argv[optind], sys_errlist[errno]);
  749.     } else {
  750.         /* Read default startup file named in files.c (autoexec.nos) */
  751.         if ((fp = fopen (Startup, READ_TEXT)) == NULLFILE)
  752.             tprintf (NoRead, Startup, sys_errlist[errno]);
  753.     }
  754.     if (fp != NULLFILE) {
  755.         char *bptr;
  756.  
  757.         inbuff = mallocw (BUFSIZ);
  758.         intmp = mallocw (BUFSIZ);
  759.         while (fgets (inbuff, BUFSIZ, fp) != NULLCHAR) {
  760.             kwait (NULL);
  761.             strncpy (intmp, inbuff, BUFSIZ);
  762.             if (Verbose == 1) {
  763.                 tprintf ("%s", intmp);
  764.                 tflush ();
  765.             } else if (Verbose == 2) {
  766.                 tprintf ("%s  Execute (*Y/n/all)", intmp);
  767.                 tflush ();
  768.                 if (recv_mbuf (Command->input, &bp, 0, NULLCHAR, 0) != -1) {
  769.                     c = toupper (*bp->data);
  770.                     free_p (bp);
  771.                     if (c == 'N')
  772.                         continue;
  773.                     if (c == 'A')
  774.                         Verbose = 1;
  775.                 }
  776.             }
  777.             Mprunning_err = 0;
  778.             bptr = _variable_expansion (strdup (inbuff));
  779.             if (cmdparse (Cmds, bptr, NULL) != 0) {
  780.                 tprintf ("input line: %s", intmp);
  781.                 rflush ();
  782.             }
  783.             free (bptr);
  784.             if (Mprunning_err)
  785.                 tprintf (MPRUNNINGerr, intmp);
  786.         }
  787.         (void) fclose (fp);
  788.         free (inbuff);
  789.         free (intmp);
  790.     }
  791.     Mprunning = 1;        /* we are on speed now */
  792. #if 0
  793.     Command->flowmode = 1;    /* set 'more' paging on command screen */
  794. #endif
  795.  
  796.     if (Warnings)
  797.         (void) dowarnings (0, NULLCHARP, (void *) 0);
  798.     reg_status ();
  799.  
  800. #ifdef BROWSER
  801.     if (UpdateTimeout)    {
  802.         char const *myargv[3];
  803.         char numbuf[10], url[60];
  804.  
  805.         tprintf ("\nAutosearching for updates at lantz.com - waiting maximum of %d seconds\n"
  806.              "To avoid this in the future, add '-U 0' to your TNOS commandline\n",
  807.              UpdateTimeout);
  808.  
  809.         sprintf (numbuf, "%d", UpdateTimeout);
  810.         myargv[1] = numbuf;
  811.         strcpy (url, "http://www.lantz.com/tnos/updates.html?NOT");
  812.         if (is_registered())
  813.             strcpy (url, "http://www.lantz.com/tnos/updates.html");
  814.         myargv[2] = url;
  815.         kwait (NULL);
  816.         (void) dobrowsercheck (3, (char **) myargv, (void *) 0);
  817.     }
  818. #endif
  819.     /* Now loop forever, processing commands */
  820.     for (;;) {
  821.         netPrompt ();
  822.         if (recv_mbuf (Command->input, &bp, 0, NULLCHAR, 0) != -1) {
  823.             logcmd ((char *) bp->data);
  824.             variable_expansion (&bp);
  825.             (void) cmdparse (Cmds, (char *) bp->data, Lastcurr);
  826.             free_p (bp);
  827.  
  828.         }
  829.         if (Warnings && !(++cmdcounter % 20))
  830.             (void) dowarnings (0, NULLCHARP, (void *) 0);
  831.     }
  832. }
  833.  
  834.  
  835.  
  836. int
  837. chksession (struct session *sp)
  838. {
  839. #ifdef TRACE
  840.     return (((sp->type != COMMAND) && (sp != Trace) && (sp->type != FREE)) ? 1 : 0);
  841. #else
  842.     return (((sp->type != COMMAND) && (sp->type != FREE)) ? 1 : 0);
  843. #endif
  844. }
  845.  
  846.  
  847.  
  848. /* Keyboard input process */
  849. /* Modified to support F-key session switching,
  850.  * from the WNOS3 sources - WG7J
  851.  */
  852. void
  853. keyboard (int i OPTIONAL, void *v1 OPTIONAL, void *v2 OPTIONAL)
  854. {
  855. int c;
  856. struct mbuf *bp;
  857. register int j, k;
  858. struct session *sp;
  859. int got = 0;
  860.  
  861.     /* Keyboard process loop */
  862.     for (;;) {
  863.         c = kbread ();
  864. #ifdef MSDOS
  865.         if (c == -1)
  866.             continue;
  867. #endif
  868. #ifdef SCREENSAVER
  869.         LastIO = secclock();
  870.         if (ssenabled())
  871.             screensaver ();
  872. #endif
  873.         
  874. #if (!defined(MSDOS) || defined(ESCAPE))
  875.         if (c == Escape && Escape != 0)
  876.             c = -2;
  877. #endif
  878.         if (c == -2 && Current != Command) {
  879.             /* Save current tty mode and set cooked */
  880.             /*            swapscreen(Current,Command); */
  881.             Lastcurr = Current;
  882.             Current = Command;
  883.             swapscreen (Lastcurr, Current);
  884.  
  885. #if 0
  886.             /* set 'more' paging on command screen */
  887.             Command->flowmode = 1;
  888. #endif
  889.         }
  890.         if (c < -2) {    /* F1 to F9 (or INSERT) pressed */
  891.             switch (c) {
  892. #ifdef TRACE
  893.                 case -11:    /* If F9 is pressed, -11 is returned and we swap to Trace - WG7J */
  894.                     if (Tracesession) {
  895.                         if (Current != Trace) {
  896.                             /* Save current tty mode and set cooked */
  897.                             /*                        swapscreen(Current,Trace); */
  898.                             BLOCKStatline = 1;
  899.                             while (INStatline)
  900.                                 kwait (NULL);
  901.                             Lastcurr = Current;
  902.                             Current = Trace;
  903.                             swapscreen (Lastcurr, Current);
  904.                             BLOCKStatline = 0;
  905.  
  906.                             /* turn off 'more' paging on trace screen */
  907.                             Trace->flowmode = 0;
  908.                         } else {
  909.                             /* Toggle back to previous session */
  910.                             /*                        swapscreen(Trace,Lastcurr); */
  911.                             BLOCKStatline = 1;
  912.                             while (INStatline)
  913.                                 kwait (NULL);
  914.                             if (Lastcurr == NULLSESSION)
  915.                                 Current = Command;
  916.                             else
  917.                                 Current = Lastcurr;
  918.                             Lastcurr = Trace;
  919.                             swapscreen (Lastcurr, Current);
  920.                             BLOCKStatline = 0;
  921.                         }
  922.                     }
  923.                     break;
  924. #endif
  925.                 case -105:    /* INSERT pressed, statline toggle */
  926.                     statLineToggle (1);
  927.                     break;
  928.                 case -106:    /* DEL pressed, toggle flow control */
  929.                     Current->flowmode ^= 1;
  930.                     break;
  931.                 case -107:    /* HOME pressed, kick current session */
  932.                     (void) dokick (0, 0, Current);
  933.                     break;
  934.                 case -108:    /* END pressed, end current session */
  935.                     (void) doreset (0, 0, Current);
  936.                     break;
  937.                 case -109:    /* PGUP pressed, goto previous session */
  938.                     j = (int) (((Current->index - 1) > 0) ? Current->index - 1 : (int) Nsessions - 1);
  939.                     for (sp = &Sessions[j]; sp > Sessions; sp--)
  940.                         if ((got = chksession (sp)) != 0)
  941.                             break;
  942.                     if (!got)
  943.                         for (sp = &Sessions[Nsessions - 1]; sp > Current; sp--)
  944.                             if ((got = chksession (sp)) != 0)
  945.                                 break;
  946.                     if (got) {
  947.                         /*                    swapscreen(Current,sp); */
  948.                         Lastcurr = Current;
  949.                         Current = sp;
  950.                         swapscreen (Lastcurr, Current);
  951.                     }
  952.                     break;
  953.                 case -110:    /* PGDN pressed, goto next session */
  954.                     for (sp = &Sessions[Current->index + 1]; sp < &Sessions[Nsessions]; sp++)
  955.                         if ((got = chksession (sp)) != 0)
  956.                             break;
  957.                     if (!got)
  958.                         for (sp = Sessions; sp < Current; sp++)
  959.                             if ((got = chksession (sp)) != 0)
  960.                                 break;
  961.                     if (got) {
  962.                         /*                    swapscreen(Current,sp); */
  963.                         Lastcurr = Current;
  964.                         Current = sp;
  965.                         swapscreen (Lastcurr, Current);
  966.                     }
  967.                     break;
  968.                 default:
  969.                     k = (-1 * c) - 2;
  970.                     for (sp = Sessions, j = 0; sp < &Sessions[Nsessions]; sp++) {
  971.                         if (sp->type == COMMAND)
  972.                             continue;
  973.                         j++;
  974.                         if (sp->type != FREE && j == k) {
  975.                             /*                        swapscreen(Current,sp); */
  976.                             Lastcurr = Current;
  977.                             Current = sp;
  978.                             swapscreen (Lastcurr, Current);
  979.                             break;
  980.                         }
  981.                     }
  982.             }
  983.         }
  984.         /*        Current->row = MOREROWS; */
  985.         Current->row = SCREENlength - 1 - (Current->split * 2);
  986.         ksignal (&Current->row, 1);
  987.         if (c >= 0) {
  988. #ifdef UNIX
  989.             if (Current->morewait)    /* end display pause, if any */
  990.                 Current->morewait = 2;
  991. #endif
  992.             /* If the screen driver was in morewait state, this char
  993.              * has woken him up. Toss it so it doesn't also get taken
  994.              * as normal input. If the char was a command escape,
  995.              * however, it will be accepted; this gives the user
  996.              * a way out of lengthy output.
  997.              */
  998.             if (!Current->morewait && (bp = ttydriv (Current, c)) != NULLBUF)
  999.                 (void) send_mbuf (Current->input, bp, 0, NULLCHAR, 0);
  1000.         }
  1001.     }
  1002. }
  1003.  
  1004.  
  1005. #ifdef LOCK
  1006. extern int Kblocked;
  1007. extern char *Kbpasswd;
  1008.  
  1009.  
  1010. /*Lock the keyboard*/
  1011. int
  1012. dolock (int argc, char *argv[], void *p OPTIONAL)
  1013. {
  1014.     if (argc == 1) {
  1015.         if (Kbpasswd == NULLCHAR)
  1016.             tputs ("Set password first\n");
  1017.         else {
  1018.             Kblocked = 1;
  1019.             tputs ("Keyboard locked\n");
  1020.             Command->ttystate.echo = 0;    /* Turn input echoing off! */
  1021.         }
  1022.         return 0;
  1023.     }
  1024.     if (argc == 3) {
  1025.         if (*argv[1] == 'p') {    /*set the password*/
  1026.             if (Kbpasswd != NULLCHAR) {
  1027.                 free (Kbpasswd);
  1028.                 Kbpasswd = NULLCHAR;    /* reset the pointer */
  1029.             }
  1030.             if (!strlen (argv[2]))
  1031.                 return 0;    /* clearing the buffer */
  1032.             Kbpasswd = strdup (argv[2]);
  1033.             return 0;
  1034.         }
  1035.     }
  1036.     tputs ("Usage: lock password \"<unlock password>\"\nor    'lock' to lock the keyboard\n");
  1037.  
  1038.     return 0;
  1039. }
  1040.  
  1041.  
  1042.  
  1043. /*Unlock the keyboard remotely*/
  1044. int
  1045. dounlock (int argc, char *argv[], void *p OPTIONAL)
  1046. {
  1047.     if (argc == 1)
  1048.         tputs ("Usage: unlock \"<unlock password>\"\n to unlock the keyboard\n");
  1049.     else if (!stricmp (Kbpasswd, argv[1])) {
  1050.         Kblocked = 0;
  1051.         tputs ("Keyboard unlocked\n");
  1052.         Command->ttystate.echo = 1;    /* Turn input echoing off! */
  1053.     }
  1054.     return 0;
  1055. }
  1056.  
  1057. #endif
  1058.  
  1059.  
  1060.  
  1061. /* Choose the prompt type */
  1062. int
  1063. doprompt (int argc, char *argv[], void *p OPTIONAL)
  1064. {
  1065. char const *str;
  1066.  
  1067.     if (argc == 1) {
  1068.         switch (PromptType) {
  1069.             case 3:
  1070.                 str = "Custom";
  1071.                 break;
  1072.             case 2:
  1073.                 str = "Dirname";
  1074.                 break;
  1075.             case 1:
  1076.                 str = "Hostname";
  1077.                 break;
  1078.             default:
  1079.                 str = "Normal";
  1080.         }
  1081.         tprintf ("Prompt: %s %c %s\n", str, (PromptType == 3) ? '-' : ' ', (PromptType == 3) ? Customprompt : "");
  1082.         return 0;
  1083.     }
  1084.     switch (*argv[1]) {
  1085.         case 'n':
  1086.             PromptType = 0;    /* use the normal prompt */
  1087.             break;
  1088.         case 'h':
  1089.             PromptType = 1;    /* use the hostname */
  1090.             break;
  1091.         case 'd':
  1092.             PromptType = 2;    /* use the dirname */
  1093.             break;
  1094.         case 'c':
  1095.             PromptType = 3;    /* set a custom prompt */
  1096.             break;
  1097.         default:
  1098.             tputs ("Usage: prompt [hostname | dirname | normal | custom 'promptstr']\n");
  1099.             return 0;
  1100.     }
  1101.     if (Customprompt != NULLCHAR) {
  1102.         free (Customprompt);
  1103.         Customprompt = NULLCHAR;
  1104.     }
  1105.     if (PromptType == 3)
  1106.         Customprompt = strdup (argv[2]);
  1107.     return 0;
  1108. }
  1109.  
  1110.  
  1111.  
  1112. #ifdef ALLCMD
  1113. /* Standard commands called from main */
  1114. int
  1115. dodelete (int argc, char *argv[], void *p OPTIONAL)
  1116. {
  1117. int i;
  1118. char filenm[13], *cp, fullname[128];
  1119. char fname[128];
  1120. #ifdef DOS_GETFILEATTR
  1121. unsigned attr;
  1122. #endif
  1123.  
  1124.     for (i = 1; i < argc; i++) {
  1125.         strncpy (fname, make_fname (Command->curdirs->dir, argv[i]), 128);
  1126. #ifdef DOS_GETFILEATTR
  1127.         if (!_dos_getfileattr (fname, &attr) && (attr & FA_DIREC)) {
  1128.             strcat (fname, "/*.*");
  1129.             tputs ("All files in directory will be deleted!\nAre you sure (Y/N)? ");
  1130.             usflush (Curproc->output);
  1131.             if (recvline (Curproc->input, (unsigned char *) filenm, 13) == -1)
  1132.                 break;
  1133.             if (toupper (*filenm) != 'Y')
  1134.                 continue;
  1135.             cp = (char *) 1;
  1136.         }
  1137. #endif
  1138.         (void) filedir (fname, 0, filenm);
  1139.         if ((cp = strrchr (fname, '/')) != NULLCHAR)
  1140.             *cp = 0;
  1141.         for (; *filenm; (void) filedir (fname, 1, filenm)) {
  1142.             if (*filenm == '.' && (!filenm[1] || (filenm[1] == '.' && !filenm[2])))
  1143.                 continue;
  1144.             sprintf (fullname, "%s%s%s", (cp) ? fname : "", (cp) ? "/" : "", filenm);
  1145.             if (unlink (fullname) == -1)
  1146.                 tprintf ("Can't delete %s: %s\n", fullname, sys_errlist[errno]);
  1147.         }
  1148.     }
  1149.     return 0;
  1150. }
  1151.  
  1152.  
  1153.  
  1154. int
  1155. dorename (int argc OPTIONAL, char *argv[], void *p OPTIONAL)
  1156. {
  1157. char fname1[128];
  1158. char fname2[128];
  1159.  
  1160.     strncpy (fname1, make_fname (Command->curdirs->dir, argv[1]), 128);
  1161.     strncpy (fname2, make_fname (Command->curdirs->dir, argv[2]), 128);
  1162.     if (rename (fname1, fname2) == -1)
  1163.         tprintf ("Can't rename: %s\n", sys_errlist[errno]);
  1164.     return 0;
  1165. }
  1166.  
  1167.  
  1168.  
  1169. int
  1170. docopy (int argc, char *argv[], void *p OPTIONAL)
  1171. {
  1172. register FILE *old, *new;
  1173. register int ch;
  1174. register unsigned char count;
  1175. char filenm[13], *dirnam = NULL, *cp, fullname[512];
  1176. int usedir = 0;
  1177. char fname[128], fname2[128];
  1178. #ifdef DOS_GETFILEATTR
  1179. unsigned attr;
  1180. #endif
  1181.  
  1182.     if (argc > 2) {
  1183.         strncpy (fname2, make_fname (Command->curdirs->dir, argv[2]), 128);
  1184. #ifdef DOS_GETFILEATTR
  1185.         (void) _dos_getfileattr (fname2, &attr);
  1186.         if (attr & FA_DIREC) {
  1187.             usedir = 1;
  1188.             dirnam = fname2;
  1189.         }
  1190. #endif
  1191.     } else
  1192.         usedir = 1;
  1193.     strncpy (fname, make_fname (Command->curdirs->dir, argv[1]), 128);
  1194. #ifdef DOS_GETFILEATTR
  1195.     if (!_dos_getfileattr (fname, &attr) && (attr & FA_DIREC)) {
  1196.         strcat (fname, "/*.*");
  1197.         cp = (char *) 1;
  1198.     }
  1199. #endif
  1200.     (void) filedir (fname, 0, filenm);
  1201.     if ((cp = strrchr (fname, '/')) != NULLCHAR)
  1202.         *cp = 0;
  1203.     for (; *filenm; (void) filedir (fname, 1, filenm)) {
  1204.         if (*filenm == '.' && (!filenm[1] || (filenm[1] == '.' && !filenm[2])))
  1205.             continue;
  1206.         sprintf (fullname, "%s%s%s", (cp) ? fname : "", (cp) ? "/" : "", filenm);
  1207.         if ((old = fopen (fullname, READ_BINARY)) == NULL) {
  1208.             tprintf ("Can't open %s: %s\n", fullname, sys_errlist[errno]);
  1209.             continue;
  1210.         }
  1211.         sprintf (fullname, "%s%s%s", (dirnam) ? dirnam : "", (dirnam) ? "/" : "", (usedir) ? filenm : fname2);
  1212.         if ((new = fopen (fullname, WRITE_BINARY)) == NULL) {
  1213.             tprintf ("Can't open %s: %s\n", fullname, sys_errlist[errno]);
  1214.             (void) fclose (old);
  1215.             continue;
  1216.         }
  1217.         (void) strlwr (fullname);
  1218.         tprintf ("Copying '%s'...\n", fullname);
  1219.         /* Now go copy */
  1220.         count = 0;
  1221.         while ((ch = fgetc (old)) != EOF) {
  1222.             if (fputc (ch, new) == EOF) {
  1223.                 tputs ("Copy failed!\n");
  1224.                 break;
  1225.             }
  1226.             if (!(++count))    /* be polite to other users */
  1227.                 kwait (NULL);
  1228.         }
  1229.         (void) fclose (old);
  1230.         (void) fclose (new);
  1231.         if (!usedir)
  1232.             break;
  1233.     }
  1234.     return 0;
  1235. }
  1236.  
  1237. #endif /*ALLCMD*/
  1238.  
  1239.  
  1240.  
  1241. /*this is also called from the remote-server for the 'exit' command - WG7J*/
  1242. void
  1243. where_outta_here (resetme, where)
  1244. int resetme;            /* resetme is 0=exit, 1=low memory, 2=reset (if possible), 3=free lockup error, 5=proc loop error */
  1245. char const *where;
  1246. {
  1247. time_t StopTime;
  1248. FILE *fp;
  1249. char *inbuff, *intmp;
  1250. char *bptr;
  1251.  
  1252.     tcmdprintf ("*** Exiting TNOS...\n");
  1253.     if (NextCmd)
  1254.         NextCmd = 1;
  1255. #if 0
  1256.     inbuff = NextCmdMsg;
  1257.     NextCmdMsg = NULLCHAR;
  1258.     free (inbuff);
  1259. #endif
  1260.  
  1261.     /* Execute sequence of commands taken from file "~/onexit.nos" */
  1262.     /* From iw0cnb */
  1263.     /* only if we got here for a reason OTHER than low memory!! ko4ks */
  1264.     if ((resetme & 1) != 1 && (fp = fopen (Onexit, READ_TEXT)) != NULLFILE) {
  1265.         inbuff = mallocw (BUFSIZ);
  1266.         intmp = mallocw (BUFSIZ);
  1267.         while (fgets (inbuff, BUFSIZ, fp) != NULLCHAR) {
  1268.             strncpy (intmp, inbuff, BUFSIZ);
  1269.             if (Verbose) {
  1270.                 tprintf ("%s", intmp);
  1271.                 rflush ();
  1272.             }
  1273.             bptr = _variable_expansion (strdup (inbuff));
  1274.             if (cmdparse (Cmds, bptr, NULL) != 0)    {
  1275.                 tprintf ("input line: %s", intmp);
  1276.                 rflush ();
  1277.             }
  1278.             free (bptr);
  1279.         }
  1280.         (void) fclose (fp);
  1281.         free (inbuff);
  1282.         free (intmp);
  1283.     }
  1284.     StopTime = time (&StopTime);
  1285.     main_exit = TRUE;    /* let everyone know we're out of here */
  1286. #ifdef AX25
  1287. #ifdef MBFWD
  1288.     FWDmode = 0;        /* disable future forwarding sessions */
  1289. #endif
  1290.     if (resetme != 3 && resetme != 5)    {
  1291.         reset_all_ax25 ();
  1292.         kpause (2000);
  1293.     }
  1294. #endif
  1295.     reset_all ();
  1296.     if (Dfile_updater != NULLPROC)
  1297.         alert (Dfile_updater, 0);    /* don't wait for timeout */
  1298.  
  1299.     kpause (1000);    /* Allow tasks some time to complete */
  1300. #ifdef TRACE
  1301.     shuttrace ();
  1302. #endif
  1303. #if defined(MSDOS)
  1304.     DOSterm ();
  1305. #endif
  1306.     log (-1, "TNOS was stopped from '%s' with value %d", where, resetme);
  1307. #ifdef STATS
  1308.     if (!resetme)
  1309.         (void) doSTATsave (0, (char **) 0, (void *) 0);
  1310. #endif
  1311.     if (Logfp) {
  1312.         (void) fclose (Logfp);
  1313.         Logfp = NULLFILE;
  1314.     }
  1315. #ifdef UNIX
  1316.     detach_all_asy ();    /* make sure everything is unlocked */
  1317.     kwait (NULL);
  1318. #endif
  1319.     iostop ();
  1320.     freehistory ();
  1321.     free_dirs (Command->curdirs);
  1322. #ifdef TNOS_68K
  1323.     alm_delete (TNOS_68KAlarm);
  1324. #endif
  1325.  
  1326. #ifdef UNIX
  1327. #if 0
  1328.     if (resetme && resetme != 1) {
  1329.         int pid;
  1330.  
  1331.         if ((pid = fork ()) == 0)
  1332.             abort ();
  1333.         /* this SHOULD take care of clearing vombie processes */
  1334.         waitpid (pid, NULL, WNOHANG);
  1335.         execvp (origargv[0], origargv);    /* re-run NOS */
  1336.     }
  1337. #endif
  1338.     {
  1339.         char *rp = mallocw (sizeof (rootdir) + 2 + sizeof (LockName));
  1340.         sprintf (rp, "%s/%s", rootdir, LockName);
  1341.         (void) unlink (rp);
  1342.         free (rp);
  1343.     }
  1344. #else
  1345.     if (resetme)
  1346.         sysreset ();
  1347. #endif
  1348.     exit (0);
  1349. }
  1350.  
  1351.  
  1352.  
  1353. int
  1354. doexit (int argc, char *argv[], void *p OPTIONAL)
  1355. {
  1356. int c;
  1357. struct mbuf *bp;
  1358. time_t nowtime, elapsedtime;
  1359. unsigned int days, hrs, mins, secs;
  1360.  
  1361.     if (strnicmp (Curproc->name, "at ", 3) == 0 ||
  1362.         strnicmp (Curproc->name, "Cron ", 5) == 0)
  1363.         where_outta_here (0, "doexit");
  1364.  
  1365.     if (Curproc->input != Command->input)
  1366.         return -2;    /*probably mailbox-sysop */
  1367.     if (argc == 2)
  1368.         c = argv[1][0];
  1369.     else {
  1370.         tputs ("\007Exit TNOS: Are you sure? ");
  1371.         tflush ();
  1372.         (void) recv_mbuf (Command->input, &bp, 0, NULLCHAR, 0);
  1373.         c = bp->data[0];
  1374.     }
  1375.     if (c != 'y' && c != 'Y') {
  1376.         Command->ttystate.edit = Command->ttystate.echo = 1;
  1377.         return 0;    /* signal delete of message */
  1378.     }
  1379.     nowtime = time (&nowtime);    /* current time */
  1380.     elapsedtime = nowtime - StartTime;    /* nos elapsed time */
  1381.     secs = (unsigned int) ((long) elapsedtime % 60);
  1382.     elapsedtime = elapsedtime / 60;
  1383.     mins = (unsigned int) ((long) elapsedtime % 60);
  1384.     elapsedtime = elapsedtime / 60;
  1385.     hrs = (unsigned int) ((long) elapsedtime % 24);
  1386.     elapsedtime = elapsedtime / 24;
  1387.     days = (unsigned int) (long) elapsedtime;
  1388.     tprintf ("TNOS Exiting - Runtime => %u days:%02u hours:%02u minutes:%02u seconds.\n", days, hrs, mins, secs);
  1389.     tflush ();
  1390.     kpause (1500);
  1391.     where_outta_here (0, "doexit");    /*No reset!*/
  1392. #if !defined(_lint)
  1393.     return 0;    /* to silence compiler warning */
  1394. #endif
  1395. }
  1396.  
  1397.  
  1398. extern char Chostname[], CConsole[];
  1399.  
  1400. #define CNAMELEN 16
  1401.  
  1402.  
  1403.  
  1404. int
  1405. dohostname (int argc, char *argv[], void *p OPTIONAL)
  1406. {
  1407. #ifdef CONVERS
  1408. char *cp;
  1409. #endif
  1410.  
  1411.     if (argc < 2) {
  1412.         if (Hostname)
  1413.             tprintf ("%s\n", Hostname);
  1414.     } else {
  1415.         struct iface *ifp;
  1416.         char *name;
  1417.  
  1418.         if ((ifp = if_lookup (argv[1])) != NULLIF) {
  1419.             if ((name = resolve_a (ifp->addr, FALSE)) == NULLCHAR) {
  1420.                 tputs ("Interface address not resolved\n");
  1421.                 return 1;
  1422.             } else {
  1423.                 if (Hostname != NULLCHAR)
  1424.                     free (Hostname);
  1425.                 Hostname = name;
  1426.                 tprintf ("Hostname set to %s\n", name);
  1427.             }
  1428.         } else {
  1429.             if (Hostname != NULLCHAR)
  1430.                 free (Hostname);
  1431.             Hostname = strdup (argv[1]);
  1432.             /* Remove trailing dot */
  1433.             if (Hostname[strlen (Hostname) - 1] == '.')
  1434.                 Hostname[strlen (Hostname) - 1] = '\0';
  1435.         }
  1436. #ifdef CONVERS
  1437.         /* If convers hostname not set yet, set it to first 10 chars
  1438.          * of the hostname. If there are '.' from the right, cut off
  1439.          * before that. - WG7J
  1440.          */
  1441.         if (Chostname[0] == '\0') {
  1442.             strncpy (Chostname, Hostname, CNAMELEN);
  1443.             if ((cp = strrchr (Chostname, '.')) != NULLCHAR)
  1444.                 *cp = '\0';
  1445.         }
  1446.         if (CConsole[0] == '\0') {
  1447.             strncpy (CConsole, Hostname, CNAMELEN);
  1448.             if ((cp = strchr (CConsole, '.')) != NULLCHAR)
  1449.                 *cp = '\0';
  1450.         }
  1451. #endif
  1452.     }
  1453.     if (Hostname && strchr (Hostname, '.') == NULLCHAR)
  1454.         tprintf ("Warning - hostname should include domain\n");
  1455.     return 0;
  1456. }
  1457.  
  1458.  
  1459.  
  1460. int
  1461. dolog (int argc, char *argv[], void *p OPTIONAL)
  1462. {
  1463. static char *logname = NULLCHAR;
  1464. char fname[128];
  1465.  
  1466.     if (argc < 2) {
  1467.         if (Logfp && logname != NULLCHAR)
  1468.             tprintf ("Logging to %s\n", logname);    /* lint !e727 */
  1469.         else
  1470.             tputs ("Logging off\n");
  1471.         return 0;
  1472.     }
  1473.     if (Logfp) {
  1474.         log (-1, "TNOS log closed");
  1475.         (void) fclose (Logfp);
  1476.         Logfp = NULLFILE;
  1477.         free (logname);
  1478.         logname = NULLCHAR;
  1479.     }
  1480.     if (strcmp (argv[1], "stop") && strcmp (argv[1], "off")) {
  1481.         strncpy (fname, make_fname (Command->curdirs->dir, argv[1]), 128);
  1482.         logname = strdup (fname);
  1483.         Logfp = fopen (logname, APPEND_TEXT);
  1484.         log (-1, "TNOS v%s was started at %s", Version, TZTIME (&StartTime));
  1485.     }
  1486.     return 0;
  1487. }
  1488.  
  1489.  
  1490.  
  1491. /* Attach an interface
  1492.  * Syntax: attach <hw type> <I/O address> <vector> <mode> <label> <bufsize> [<speed>]
  1493.  */
  1494. int
  1495. doattach (int argc, char *argv[], void *p)
  1496. {
  1497.     return subcmd (Attab, argc, argv, p);
  1498. }
  1499.  
  1500.  
  1501.  
  1502. /* Manipulate I/O device parameters */
  1503. int
  1504. doparam (int argc, char *argv[], void *p OPTIONAL)
  1505. {
  1506. int param, set;
  1507. int32 val;
  1508. register struct iface *ifp;
  1509.  
  1510.     if ((ifp = if_lookup (argv[1])) == NULLIF) {
  1511.         tprintf (Badinterface, argv[1]);
  1512.         return 1;
  1513.     }
  1514.     if (ifp->ioctl == NULL) {
  1515.         tputs ("Not supported\n");
  1516.         return 1;
  1517.     }
  1518.     if (argc < 3) {
  1519.         for (param = 1; param <= 16; param++) {
  1520.             val = (*ifp->ioctl) (ifp, param, FALSE, 0L);
  1521.             if (val != -1)
  1522.                 tprintf ("%s: %ld\n", parmname (param), val);
  1523.         }
  1524.         return 0;
  1525.     }
  1526.     param = devparam (argv[2]);
  1527.     if (param == -1) {
  1528.         tprintf ("Unknown parameter %s\n", argv[2]);
  1529.         return 1;
  1530.     }
  1531.     if (argc < 4) {
  1532.         set = FALSE;
  1533.         val = 0L;
  1534.     } else {
  1535.         set = TRUE;
  1536.         val = atol (argv[3]);
  1537.     }
  1538.     val = (*ifp->ioctl) (ifp, param, set, val);
  1539.     if (val == -1)
  1540.         tprintf ("Parameter %s not supported\n", argv[2]);
  1541.     else
  1542.         tprintf ("%s: %ld\n", parmname (param), val);
  1543.     return 0;
  1544. }
  1545.  
  1546.  
  1547.  
  1548. /* Display or set IP interface control flags */
  1549. int
  1550. domode (int argc, char *argv[], void *p OPTIONAL)
  1551. {
  1552. register struct iface *ifp;
  1553.  
  1554.     if ((ifp = if_lookup (argv[1])) == NULLIF) {
  1555.         tprintf (Badinterface, argv[1]);
  1556.         return 1;
  1557.     }
  1558.     if (argc < 3) {
  1559.         tprintf ("%s: %s\n", ifp->name,
  1560.             (ifp->flags & CONNECT_MODE) ? "VC mode" : "Datagram mode");
  1561.         return 0;
  1562.     }
  1563.     switch (argv[2][0]) {
  1564.         case 'v':
  1565.         case 'c':
  1566.         case 'V':
  1567.         case 'C':
  1568.             ifp->flags |= CONNECT_MODE;
  1569.             break;
  1570.         case 'd':
  1571.         case 'D':
  1572.             ifp->flags &= ~CONNECT_MODE;
  1573.             break;
  1574.         default:
  1575.             tprintf ("Usage: %s [vc | datagram]\n", argv[0]);
  1576.             return 1;
  1577.     }
  1578.     return 0;
  1579. }
  1580.  
  1581.  
  1582.  
  1583. #if    (!defined(MSDOS) || defined(ESCAPE))
  1584. int
  1585. doescape (int argc, char *argv[], void *p OPTIONAL)
  1586. {
  1587.     if (argc < 2)
  1588.         tprintf ("0x%x\n", Escape);
  1589.     else
  1590.         Escape = (char) htoi (argv[1]);
  1591.     return 0;
  1592. }
  1593. #endif /* MSDOS */
  1594.  
  1595.  
  1596.  
  1597. /* Generate system command packet. Synopsis:
  1598.  * remote [-p <port#>] [-a <kickaddress>] <hostname> kickme
  1599.  * remote [-p <port#>] -k <key> <hostname> reset|exit
  1600.  * remote [-p <port#>] -k <key> -r <destIPaddr>[/<bits>] <hostname> add|drop
  1601.  * remote -s <password>
  1602.  * remote -g <gatewaypassword>
  1603.  */
  1604. int
  1605. doremote (int argc, char *argv[], void *p OPTIONAL)
  1606. {
  1607. struct sockaddr_in fsock;
  1608. int s, c;
  1609. char *data, x;
  1610. int16 port, len;
  1611. char *key = NULLCHAR;
  1612. int klen = 0;
  1613. uint32 addr = 0;
  1614. char *cmd, *host;
  1615. char *route = NULLCHAR;
  1616.  
  1617.     port = IPPORT_REMOTE;    /* Set default */
  1618.     optind = 0;        /* reinit getopt() */
  1619.     while ((c = getopt (argc, argv, "a:r:g:p:k:s:x:")) != EOF) {
  1620.         switch (c) {
  1621.             case 'a':
  1622.                 if ((addr = resolve (optarg)) == 0) {
  1623.                     tprintf (Badhost, optarg);
  1624.                     return -1;
  1625.                 }
  1626.                 break;
  1627.             case 'p':
  1628.                 port = (int16) atoi (optarg);
  1629.                 break;
  1630.             case 'k':
  1631.                 key = optarg;
  1632.                 klen = (int) strlen (key);
  1633.                 break;
  1634.             case 's':
  1635.                 Rempass = strdup (optarg);
  1636.                 return 0;    /* Only set local password */
  1637. #ifdef ENCAP
  1638.             case 'r':
  1639.                 route = optarg;
  1640.                 break;
  1641.             case 'g':
  1642.                 RemRTpass = strdup (optarg);
  1643.                 return 0;    /* Only set local password for adding routes */
  1644. #else
  1645.             case 'r':
  1646.             case 'g':
  1647.                 tputs ("This option is not available to you. TNOS was NOT compiled\nwith support for the ENCAP features!\n");
  1648.                 /* and fall through */
  1649. #endif
  1650.             default:
  1651.                 return 0;
  1652.         }
  1653.     }
  1654.     if (optind > argc - 2) {
  1655.         tputs ("Insufficient args\n");
  1656.         return -1;
  1657.     }
  1658.     host = argv[optind];
  1659.     cmd = argv[optind + 1];
  1660.     if ((s = socket (AF_INET, SOCK_DGRAM, 0)) == -1) {
  1661.         tputs ("socket failed\n");
  1662.         return 1;
  1663.     }
  1664.     len = 1;
  1665.     /* Did the user include a password or kickme target? */
  1666.     if (addr != 0 && cmd[0] == 'k')
  1667.         len += sizeof (int32);
  1668.  
  1669.     if (key != NULLCHAR && cmd[0] != 'k')
  1670.         len += (int16) klen;
  1671.  
  1672.     if (route != NULLCHAR)
  1673.         len += (int16) (strlen (route) + 1);
  1674.  
  1675.     if (len == 1)
  1676.         data = &x;
  1677.     else
  1678.         data = mallocw ((size_t) len);
  1679.  
  1680.     fsock.sin_family = AF_INET;
  1681.     if ((fsock.sin_addr.s_addr = resolve (host)) == 0) {
  1682.         tprintf (Badhost, host);
  1683.         goto cleanup;
  1684.     }
  1685.     fsock.sin_port = port;
  1686.  
  1687.     switch (cmd[0]) {
  1688.         case 'r':
  1689.         case 'e':
  1690.             data[0] = (cmd[0] == 'r') ? SYS_RESET : SYS_EXIT;
  1691.             if (key != NULLCHAR)
  1692.                 strncpy (&data[1], key, (unsigned) klen);    /*lint !e661 */
  1693.             break;
  1694.         case 'k':
  1695.             data[0] = KICK_ME;
  1696.             if (addr != 0)
  1697.                 (void) put32 ((unsigned char *) &data[1], addr);    /*lint !e661 */
  1698.             break;
  1699.         case 'a':    /* add a route */
  1700.         case 'd':    /* drop a route */
  1701.             if (key == NULLCHAR || route == NULLCHAR)    {
  1702.                 tprintf ("Command '%s' requires a password and a route entry!\n", cmd);
  1703.                 goto cleanup;
  1704.             }
  1705.             data[0] = (cmd[0] == 'a') ? ROUTE_ADD : ROUTE_DROP;
  1706.             data[1] = (char) strlen(route);        /*lint !e661 */
  1707.             strcpy (&data[2], route);        /*lint !e661 !e662 */
  1708.             strncpy (&data[2 + strlen(route)], key, (unsigned) klen);    /*lint !e661 */
  1709.             break;
  1710.         default:
  1711.             tprintf ("Unknown command %s\n", cmd);
  1712.             goto cleanup;
  1713.     }
  1714.  
  1715.     /* Form the command packet and send it */
  1716.     if (sendto (s, data, len, 0, (char *) &fsock, sizeof (fsock)) == -1) {
  1717.         tprintf ("sendto failed: %s\n", sys_errlist[errno]);
  1718.         goto cleanup;
  1719.     }
  1720. cleanup:
  1721.     if (data != &x)
  1722.         free (data);
  1723.     close_s (s);
  1724.     return 0;
  1725. }
  1726.  
  1727.  
  1728.  
  1729. #if (defined(ALLCMD) || defined(ALLSESSIONS))
  1730. int
  1731. morecmd (int argc, char *argv[], void *p OPTIONAL)
  1732. {
  1733. struct session *sp = 0;
  1734. FILE *fp;
  1735. char buf[81];
  1736. char fname[256];
  1737. int row = 0;
  1738. int usesession = 0;
  1739.  
  1740.     /* Use a session if this comes from console - WG7J*/
  1741.     if (Curproc->input == Command->input) {
  1742.         usesession = 1;
  1743.         if ((sp = newsession (argv[1], MORE, 0)) == NULLSESSION) {
  1744.             return 1;
  1745.         }
  1746.         /* Put tty into raw mode so single-char responses will work */
  1747.         sp->ttystate.echo = sp->ttystate.edit = 0;
  1748. #ifdef UNIX
  1749.         row = Numrows - 1;
  1750. #else
  1751.         row = SCREENlength;
  1752. #endif
  1753.     }
  1754.     strncpy (fname, make_fname (Command->curdirs->dir, argv[1]), 256);
  1755.     if ((fp = fopen (fname, READ_TEXT)) == NULLFILE) {
  1756.         tprintf (NoRead, fname, sys_errlist[errno]);
  1757.         if (usesession) {
  1758.             (void) keywait (NULLCHAR, 1);
  1759.             freesession (sp);
  1760.         }
  1761.         return 1;
  1762.     }
  1763.     while ((void) fgets (buf, sizeof (buf), fp), !feof (fp)) {
  1764.         if ((argc < 3) || (strstr (buf, argv[2]) != NULLCHAR)) {
  1765.             tprintf ("%s", buf);
  1766.             if (usesession) {
  1767.                 if (--row == 0) {
  1768.                     row = keywait ("--More--", 0);
  1769.                     switch (row) {
  1770.                         case -1:
  1771.                         case 'q':
  1772.                         case 'Q':
  1773.                         case 'n':
  1774.                         case 'N':
  1775.                             goto done;
  1776. #ifndef TNOS_68K
  1777.                         case '\n':
  1778. #else
  1779.                         case '\l':
  1780. #endif
  1781.                         case '\r':
  1782.                             row = 1;
  1783.                             break;
  1784.                         case ' ':
  1785.                         default:
  1786. #ifdef UNIX
  1787.                             row = Numrows - 1;
  1788. #else
  1789.                             row = SCREENlength;
  1790. #endif
  1791.                     }
  1792.                 }
  1793.             }
  1794.         }
  1795.     }
  1796. done:    (void) fclose (fp);
  1797.     if (usesession) {
  1798.         (void) keywait (NULLCHAR, 1);
  1799.         freesession (sp);
  1800.     }
  1801.     return 0;
  1802. }
  1803.  
  1804.  
  1805.  
  1806. int
  1807. domore (int argc, char *argv[], void *p)
  1808. {
  1809. char **pargv;
  1810. int i;
  1811.  
  1812.     if (Curproc->input == Command->input) {
  1813.         /* Make private copy of argv and args,
  1814.          * spawn off subprocess and return.
  1815.          */
  1816.         pargv = (char **) callocw ((size_t) argc + 1, sizeof (char *));
  1817.  
  1818.         for (i = 0; i < argc; i++)
  1819.             pargv[i] = strdup (argv[i]);
  1820.         pargv[i] = NULL;
  1821.         (void) newproc ("more", 512, (void (*)(int, void *, void *)) morecmd, argc, (void *) pargv, p, 1);
  1822.     } else
  1823.         (void) morecmd (argc, argv, p);
  1824.     return 0;
  1825. }
  1826.  
  1827.  
  1828.  
  1829. int
  1830. dotail (int argc, char *argv[], void *p OPTIONAL)
  1831. {
  1832. register int handle, i;
  1833. register unsigned line = 0, rdsize = 2000;
  1834. off_t length;
  1835. char *buffer, fname[128];
  1836. register int numlines = 18;
  1837.  
  1838.     if (argc == 3) {
  1839.         numlines = atoi (argv[2]);
  1840.         if (!numlines)
  1841.             numlines = 18;
  1842.         else
  1843.             rdsize = (unsigned) (numlines * 100);
  1844.     }
  1845.     buffer = callocw (rdsize, sizeof (char));
  1846.  
  1847.     strncpy (fname, make_fname (Command->curdirs->dir, argv[1]), 128);
  1848.     if ((handle = open (fname, O_BINARY | O_RDONLY)) == -1) {    /* lint !e718 !e746 */
  1849.         tprintf (NoRead, fname, sys_errlist[errno]);
  1850.         free (buffer);
  1851.         return -1;
  1852.     }
  1853.     length = (long) filelength (handle);
  1854.  
  1855.     if ((unsigned) length > rdsize)
  1856.         length -= (long) rdsize;
  1857.     else {
  1858.         rdsize = (unsigned) length;
  1859.         length = 0;
  1860.     }
  1861.  
  1862.     lseek (handle, length, SEEK_SET);
  1863.     if (read (handle, buffer, rdsize) == -1) {
  1864.         tprintf (NoRead, fname, sys_errlist[errno]);
  1865.         close (handle);
  1866.         free (buffer);
  1867.         return -1;
  1868.     }
  1869.     for (i = (int) rdsize - 1; i > 0; i--) {
  1870.         if (buffer[i] == '\n')
  1871.             line++;
  1872.         if (line == (unsigned) numlines)
  1873.             break;
  1874.     }
  1875.     for (; (unsigned) i < rdsize; i++)
  1876.         tputc (uchar(buffer[i]));
  1877.  
  1878.     tputc ('\n');
  1879.     close (handle);
  1880.     free (buffer);
  1881.     return 0;
  1882. }
  1883.  
  1884. #endif /*ALLCMD*/
  1885.  
  1886.  
  1887. int
  1888. doman (int argc, char *argv[], void *p)
  1889. {
  1890. char *look;
  1891. char section = '0', old = '0';
  1892. char tmp[128];
  1893. char *pargv[2];
  1894.  
  1895.     if (argc == 3) {
  1896.         old = section = argv[1][0];
  1897.         look = argv[2];
  1898.     } else
  1899.         look = argv[1];
  1900.  
  1901.     if (section == '0') {
  1902.         for (section = '1'; section <= '9'; section++) {
  1903.             sprintf (tmp, "%s/cat%c/%s.%c", MANdir, section, look, section);
  1904.             if (!access (tmp, 0))
  1905.                 break;
  1906.         }
  1907.     } else {
  1908.         sprintf (tmp, "%s/cat%c/%s.%c", MANdir, section, look, section);
  1909.         if (access (tmp, 0))
  1910.             section = '0';
  1911.     }
  1912.  
  1913.     if (section == '0' || section > '9') {
  1914.         tprintf ("No manual information found for '%s'", look);
  1915.         if (section == '0')
  1916.             tprintf (" in section %c", old);
  1917.         tputs ("\n");
  1918.     } else {
  1919.         pargv[1] = tmp;
  1920.         pargv[0] = argv[0];
  1921.         (void) domore (2, pargv, p);
  1922.     }
  1923.     return 0;
  1924. }
  1925.  
  1926.  
  1927.  
  1928. /* No-op command */
  1929. int
  1930. donothing (int argc OPTIONAL, char *argv[] OPTIONAL, void *p OPTIONAL)
  1931. {
  1932.     return 0;
  1933. }
  1934.  
  1935.  
  1936.  
  1937. int
  1938. dosystime (int argc OPTIONAL, char *argv[] OPTIONAL, void *p OPTIONAL)
  1939. {
  1940. time_t t;
  1941. struct tm *tmp;
  1942. long minutes;
  1943.  
  1944.     /* Get current time */
  1945.     (void) time (&t);
  1946.     tmp = localtime (&t);
  1947.  
  1948.     /* Print it */
  1949.     tprintf ("System time at %s (in %s): %s", Hostname,
  1950. #ifdef sun
  1951.          tmp->tm_zone,
  1952. #else
  1953. #ifdef MSDOS
  1954.          tmp->__tm_zone,
  1955. #else
  1956.          tmp->tm_isdst ? tzname[1] : tzname[0],
  1957. #endif
  1958. #endif
  1959.          asctime (tmp));
  1960.     if (argc > 1) {
  1961. #if defined(sun) || defined(__bsdi__) || defined(__FreeBSD__) || defined(MSDOS)
  1962.         minutes = tmp->tm_gmtoff / 60L;
  1963. #else
  1964.         minutes = (timezone - (tmp->tm_isdst * 3600L)) / -60L;
  1965. #endif
  1966.         tprintf ("   Local time is UTC%+ld minutes\n", minutes);
  1967.         tmp = gmtime (&t);
  1968.         tprintf ("   UTC time is %s", asctime (tmp));
  1969.     }
  1970.     return 0;
  1971. }
  1972.  
  1973.  
  1974.  
  1975. static int SendError = 1;
  1976.  
  1977. int
  1978. doerror (int argc, char *argv[], void *p OPTIONAL)
  1979. {
  1980.     return setbool (&SendError, "Mail errors", argc, argv);
  1981. }
  1982.  
  1983.  
  1984.  
  1985. #ifdef BETA
  1986. int
  1987. docrashprot (int argc, char *argv[], void *p OPTIONAL)
  1988. {
  1989.     return setbool (&CrashProtect, "Enable crash protection mode", argc, argv);
  1990. }
  1991. #endif
  1992.  
  1993.  
  1994.  
  1995. /* Mail a system message to the sysop - WG7J */
  1996. void
  1997. mail_error (const char *fmt,...)
  1998. {
  1999. FILE *txt;
  2000. va_list ap;
  2001. char *cp;
  2002. time_t t;
  2003.  
  2004.     if (!SendError)
  2005.         return;
  2006.  
  2007.     /* Create the data file */
  2008.     if ((txt = tmpfile ()) == NULL)
  2009.         return;
  2010.  
  2011.     /* Get current time */
  2012.     (void) time (&t);
  2013.  
  2014.     /* Print the text body */
  2015.     cp = ctime (&t);
  2016.     fprintf (txt, "On %s", cp);
  2017.     va_start (ap, fmt);        /*lint !e718 !e746 */
  2018.     (void) vfprintf (txt, fmt, ap);
  2019.     va_end (ap);
  2020.     fputc ('\n', txt);
  2021.     rewind (txt);
  2022.     (void) rdaemon (txt, NULLCHAR, NULLCHAR, "syserror", SysMessage, 'P', 0);
  2023.  
  2024.     (void) fclose (txt);
  2025.  
  2026.     /* Now kick the smtp server */
  2027.     smtptick (NULL);
  2028. }
  2029.  
  2030.  
  2031.  
  2032. /* Log messages of the form
  2033.  * Tue Jan 31 00:00:00 1987 44.64.0.7:1003 open FTP
  2034.  */
  2035. void
  2036. log (int s, const char *fmt,...)
  2037. {
  2038. va_list ap;
  2039. char *cp;
  2040. time_t t;
  2041. int i;
  2042. struct sockaddr fsocket;
  2043. char buf[SOBUF];
  2044. #ifdef    MSDOS
  2045. int fd;
  2046. #endif
  2047.  
  2048.     va_start (ap, fmt);        /*lint !e718 !e746 */
  2049.     (void) vsprintf (buf, fmt, ap);
  2050.     va_end (ap);
  2051.     statlog (buf);
  2052.  
  2053.     if (Logfp == NULLFILE)
  2054.         return;
  2055.  
  2056.     (void) time (&t);
  2057.     cp = TZTIME (&t);
  2058.     rip (cp);
  2059.     i = SOCKSIZE;
  2060.     fprintf (Logfp, "%s", cp);
  2061.     if (getpeername (s, (char *) &fsocket, &i) != -1)
  2062.         fprintf (Logfp, " %s", psocket (&fsocket));
  2063.  
  2064.     fprintf (Logfp, " - %s\n", buf);
  2065.     (void) fflush (Logfp);
  2066. #ifdef    MSDOS
  2067.     /* MS-DOS doesn't really flush files until they're closed */
  2068.     fd = fileno (Logfp);
  2069.     if ((fd = dup (fd)) != -1)
  2070.         close (fd);
  2071. #endif
  2072.  
  2073. }
  2074.  
  2075.  
  2076.  
  2077. /* Log messages of the form
  2078.  * Tue Jan 31 00:00:00 1987 44.64.0.7:1003 open FTP
  2079.  */
  2080. void
  2081. simple_log (int s, const char *str)
  2082. {
  2083. char *cp;
  2084. time_t t;
  2085. int i;
  2086. struct sockaddr fsocket;
  2087. #ifdef    MSDOS
  2088. int fd;
  2089. #endif
  2090.  
  2091.     statlog (str);
  2092.  
  2093.     if (Logfp == NULLFILE)
  2094.         return;
  2095.  
  2096.     (void) time (&t);
  2097.     cp = TZTIME (&t);
  2098.     rip (cp);
  2099.     i = SOCKSIZE;
  2100.     fputs (cp, Logfp);
  2101.     if (getpeername (s, (char *) &fsocket, &i) != -1)
  2102.         fprintf (Logfp, " %s", psocket (&fsocket));
  2103.  
  2104.     fputs (" - ", Logfp);
  2105.     fputs (str, Logfp);
  2106.     fputc ('\n', Logfp);
  2107.     (void) fflush (Logfp);
  2108. #ifdef    MSDOS
  2109.     /* MS-DOS doesn't really flush files until they're closed */
  2110.     fd = fileno (Logfp);
  2111.     if ((fd = dup (fd)) != -1)
  2112.         close (fd);
  2113. #endif
  2114.  
  2115. }
  2116.  
  2117.  
  2118.  
  2119. int
  2120. dosource (int argc OPTIONAL, char *argv[], void *p OPTIONAL)
  2121. {
  2122. int linenum = 0;
  2123. char *inbuff, *intmp, *bptr;
  2124. FILE *fp;
  2125. char fname[128];
  2126.  
  2127.     /* Read command source file */
  2128.     strncpy (fname, make_fname (Command->curdirs->dir, argv[1]), 128);
  2129.     if ((fp = fopen (fname, READ_TEXT)) == NULLFILE) {
  2130.         tprintf (NoRead, fname, sys_errlist[errno]);
  2131.         return 1;
  2132.     }
  2133.     inbuff = (char *) mallocw (BUFSIZ);
  2134.     intmp = (char *) mallocw (BUFSIZ);
  2135.     while (fgets (inbuff, BUFSIZ, fp) != NULLCHAR) {
  2136.         strncpy (intmp, inbuff, BUFSIZ);
  2137.         linenum++;
  2138.         if (Verbose)
  2139.             tprintf ("%s", intmp);
  2140.         if (!Mprunning)
  2141.             Mprunning_err = 0;
  2142.         bptr = _variable_expansion (strdup (inbuff));
  2143.         if (cmdparse (Cmds, bptr, NULL) != 0) {
  2144.             tprintf ("*** file \"%s\", line %d: %s\n",
  2145.                  argv[1], linenum, intmp);
  2146.         }
  2147.         free (bptr);
  2148.         if (!Mprunning && Mprunning_err)
  2149.             tprintf (MPRUNNINGerr, intmp);
  2150.     }
  2151. #ifdef SCRIPTING
  2152.     if (Curproc->gotolabel) {
  2153.         free (Curproc->gotolabel);
  2154.         Curproc->gotolabel = NULLCHAR;
  2155.     }
  2156. #endif
  2157.     (void) fclose (fp);
  2158.     free (inbuff);
  2159.     free (intmp);
  2160.     Mprunning_err = 0;
  2161.     return 0;
  2162. }
  2163.  
  2164.  
  2165.  
  2166. /* if ThirdParty is not set - restrict the mailbox (S)end command to local only */
  2167. int
  2168. dothirdparty (int argc, char *argv[], void *p OPTIONAL)
  2169. {
  2170.     return setbool (&ThirdParty, "Third-Party mail flag", argc, argv);
  2171. }
  2172.  
  2173.  
  2174.  
  2175. #if defined(ALLCMD) && !defined(UNIX)
  2176. int
  2177. domdump (int argc, char *argv[], void *p OPTIONAL)
  2178. {
  2179. unsigned int i;
  2180. char *addr;
  2181. unsigned int len = 8 * 16;    /* default is 8 lines of hex dump */
  2182.  
  2183.     if (argc < 2 || argc > 3) {
  2184.         tputs ("Usage:- dump <hex-address | .> [decimal-range] \n");
  2185.         return 0;
  2186.     }
  2187.     if (argv[1][0] == '.')
  2188.         addr = DumpAddr;/* Use last end address */
  2189.     else
  2190.         addr = (char *) htol (argv[1]);    /* get address of item being dumped */
  2191.     addr = (char *) ((((unsigned long) addr + 15) >> 4) << 4);    /* round up to modulo 16 */
  2192.  
  2193.     if (argc == 3) {
  2194.         len = atoi (argv[2]);
  2195.         len = ((len + 15) >> 4) << 4;    /* round up to modulo 16 */
  2196.     }
  2197.     if (len < 1 || len > 256) {
  2198.         tputs ("Invalid dump range. Valid is 1 to 256\n");
  2199.         return 0;
  2200.     }
  2201.     tprintf ("            Main Memory Dump Of Location %08lx\n", (long) addr);
  2202.     tputs ("Addr (offset)           Hexadecimal                         Ascii\n");
  2203.     tputs ("----                    -----------                         -----\n");
  2204.  
  2205.     for (i = 0; i < len; i += 16)
  2206.         fmtline ((uint32) (i + addr), (char *) (addr + i), 16);
  2207.     DumpAddr = (char *) (addr + i);    /* update address */
  2208.     return 0;
  2209. }
  2210.  
  2211.  
  2212.  
  2213. /* Print a buffer up to 16 bytes long in formatted hex with ascii
  2214.  * translation, e.g.,
  2215.  * 00000000: 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f  0123456789:;<=>?
  2216.  */
  2217. static void
  2218. fmtline (uint32 addr, char *buf, int16 len)
  2219. {
  2220. char line[81];
  2221. register char *aptr, *cptr;
  2222. register char c;
  2223.  
  2224.     memset (line, ' ', sizeof (line));
  2225.     ctohex (line, (int16) hibyte (addr >> 16));
  2226.     ctohex (line + 2, (int16) lobyte (addr >> 16));
  2227.     ctohex (line, (int16) hibyte (addr & 0x0000ffff));
  2228.     ctohex (line + 2, (int16) lobyte (addr & 0x0000ffff));
  2229.     aptr = &line[6];
  2230.     cptr = &line[55];
  2231.     while (len-- != 0) {
  2232.         c = *buf++;
  2233.         ctohex (aptr, (int16) uchar (c));
  2234.         aptr += 3;
  2235.         c &= 0x7f;
  2236.         if ((c > 0x1f) && (c < 0x7f))
  2237.             *cptr++ = c;
  2238.         else
  2239.             *cptr++ = '.';
  2240.     }
  2241.     *cptr++ = '\0';
  2242.     tprintf ("%s\n", line);
  2243. }
  2244.  
  2245.  
  2246.  
  2247. /* Convert byte to two ascii-hex characters */
  2248. static void
  2249. ctohex (register char *buf, register int16 c)
  2250. {
  2251. static char hex[] = "0123456789abcdef";
  2252.  
  2253.     *buf++ = hex[hinibble (c)];
  2254.     *buf = hex[lonibble (c)];
  2255. }
  2256.  
  2257. #endif
  2258.  
  2259. extern void conversWrite (char *str, char *user);
  2260.  
  2261.  
  2262.  
  2263. int
  2264. dowrite (int argc OPTIONAL, char *argv[], void *p OPTIONAL)
  2265. {
  2266. int i, s;
  2267. struct mbx *m = NULLMBX;
  2268.  
  2269. #ifdef CONVERS
  2270.     conversWrite (argv[2], argv[1]);
  2271. #endif
  2272.     if ((s = atoi (argv[1])) == 0) {    /* must be a name */
  2273. #ifdef MAILBOX
  2274.         /* check the mailbox users */
  2275.         for (i = 0; i < NUMMBX; i++) {
  2276.             if ((m = Mbox[i]) != NULLMBX) {
  2277.                 if (!strcmp (m->name, argv[1]))
  2278.                     break;
  2279.             }
  2280.         }
  2281.         if (i == NUMMBX)
  2282.             return 0;
  2283.         if (m == NULLMBX)
  2284.             return 0;
  2285.         s = m->user;
  2286. #else
  2287.         return 0;
  2288. #endif
  2289.     } else
  2290.         return 0;
  2291.     usprintf (s, FromSysop, argv[2]);
  2292.     usflush (s);
  2293.  
  2294.     return 0;
  2295. }
  2296.  
  2297.  
  2298.  
  2299. int
  2300. doshutdown (int argc OPTIONAL, char *argv[], void *p OPTIONAL)
  2301. {
  2302. int32 delayval = 0;
  2303. char *str = NULLCHAR;
  2304. char buffer[1024];
  2305.  
  2306.     str = argv[2];
  2307.  
  2308.     if (strcasecmp (argv[1], "now"))
  2309.         delayval = atol (argv[1]);
  2310.  
  2311.     if (delayval)    {
  2312.         sprintf (buffer, "System being shutdown in %ld seconds%s%s",
  2313.             delayval, (str != NULLCHAR) ? "\n*** " : "",
  2314.             (str != NULLCHAR) ? str : "");
  2315.         tcmdprintf (FromSysop, buffer);
  2316.         (void) _dowriteall (buffer);
  2317.         kpause (delayval * 1000L);
  2318.     }
  2319.  
  2320.     sprintf (buffer, "System now being shutdown%s%s",
  2321.         (str != NULLCHAR) ? "\n*** " : "",
  2322.         (str != NULLCHAR) ? str : "");
  2323.     tcmdprintf ("\n");
  2324.     tcmdprintf (FromSysop, buffer);
  2325.     (void) _dowriteall (buffer);
  2326.     kpause (5000L);
  2327.     where_outta_here (0, "doshutdown");
  2328.     return 0;            /*lint !e527 */
  2329. }
  2330.  
  2331.  
  2332.  
  2333. #ifdef MAILBOX
  2334. extern void conversWriteall (char *str);
  2335.  
  2336.  
  2337. static int
  2338. _dowriteall (char *str)
  2339. {
  2340. register struct mbx *m;
  2341. int i;
  2342.  
  2343.     for (i = 0; i < NUMMBX; i++)
  2344.         if ((m = Mbox[i]) != NULLMBX) {
  2345.             usprintf (m->user, FromSysop, str);
  2346.             usflush (m->user);
  2347.         }
  2348. #ifdef CONVERS
  2349.     conversWriteall (str);
  2350. #endif
  2351.     return 0;
  2352. }
  2353.  
  2354.  
  2355.  
  2356. /* write a message to all nodeshell users
  2357.  * argv[1] is the message.
  2358.  */
  2359. int
  2360. dowriteall (int argc OPTIONAL, char *argv[], void *p OPTIONAL)
  2361. {
  2362.     return _dowriteall (argv[1]);
  2363. }
  2364.  
  2365. #endif
  2366.  
  2367.  
  2368.  
  2369. int
  2370. dostatus (int argc OPTIONAL, char *argv[] OPTIONAL, void *p OPTIONAL)
  2371. {
  2372. time_t nowtime, elapsedtime;
  2373. unsigned int days, hrs, mins, secs;
  2374. char buf[80];
  2375.  
  2376.     nowtime = time (&nowtime);    /* current time */
  2377.     elapsedtime = nowtime - StartTime;    /* nos elapsed time */
  2378.  
  2379.     tprintf (Nosversion, Version, Version2);
  2380.     tputs (Compiled);
  2381.     if (strlen (symname) > 9) {
  2382.         strncpy (buf, &symname[7], 80);
  2383.         buf[strlen (buf) - 2] = 0;
  2384.         tprintf ("Symbolic RCS Name for this Executable: '%s'\n", buf);
  2385.     }
  2386. #ifdef MSDOS
  2387.     tprintf ("Running under %s - Version %d.%d\n", _os_flavor, _osmajor, _osminor);
  2388. #endif
  2389.     tprintf ("Tty: %d rows, %d columns\n",
  2390. #ifdef UNIX
  2391.          Numrows, Numcols);
  2392. #else
  2393.          (int) SCREENlength, (int) SCREENwidth);
  2394. #endif
  2395.  
  2396.     tprintf ("\nThe system time is %s", ctime (&nowtime));
  2397.     tprintf ("TNOS was started on %s\n", ctime (&StartTime));
  2398.     secs = (unsigned int) ((long) elapsedtime % 60);
  2399.     elapsedtime = elapsedtime / 60;
  2400.     mins = (unsigned int) ((long) elapsedtime % 60);
  2401.     elapsedtime = elapsedtime / 60;
  2402.     hrs = (unsigned int) ((long) elapsedtime % 24);
  2403.     elapsedtime = elapsedtime / 24;
  2404.     days = (unsigned int) (long) elapsedtime;
  2405.     tprintf ("Elapsed time => %u days:%02u hours:%02u minutes:%02u seconds.\n\n", days, hrs, mins, secs);
  2406.     tprintf ("Sessions = %-d, Sockets = %-d, PBBS processes = %-d", Nsessions, Nusock, NUMMBX);
  2407.     tprintf (", Serial port devices = %-d\n", ASY_MAX);
  2408.     tprintf ("AX25/SLIP devices = %-d", SLIP_MAX);
  2409. #ifdef AXIP
  2410.     tprintf (", AXIP interfaces = %-d", AXIPlinks);
  2411. #endif
  2412. #ifdef NETROM
  2413.     tprintf (", NETROM circuits = %-d", NR4MAXCIRC);
  2414. #endif
  2415.     tputs ("\n");
  2416. #ifdef UNIX
  2417.     tprintf ("Location of the LOCKDIR: %s\n", LOCKDIR);
  2418. #endif
  2419.     tputs ("\n");
  2420. #ifdef ALLCMD
  2421.     tprintf ("The station is currently %sttended.\n", Attended ? "A" : "Una");
  2422.     tputs ("The 'Message Of The Day' is ");
  2423.     if (Motd != NULLCHAR)
  2424.         tprintf ("\n%s", Motd);
  2425.     else
  2426.         tputs ("not set!\n");
  2427. #endif
  2428.     tputc ('\n');
  2429.     return 0;
  2430. }
  2431.  
  2432.  
  2433.  
  2434. #ifdef ALLCMD
  2435. int
  2436. domotd (int argc, char *argv[], void *p OPTIONAL)
  2437. {
  2438.     if (argc > 2) {
  2439.         tputs ("Usage: motd \"<your message>\"\n");
  2440.         return 1;
  2441.     }
  2442.     if (argc < 2) {
  2443.         if (Motd != NULLCHAR)
  2444.             tprintf ("%s", Motd);
  2445.     } else {
  2446.         if (Motd != NULLCHAR) {
  2447.             free (Motd);
  2448.             Motd = NULLCHAR;    /* reset the pointer */
  2449.         }
  2450.         if (!strlen (argv[1]))
  2451.             return 0;    /* clearing the buffer */
  2452.  
  2453.         Motd = mallocw (strlen (argv[1]) + 2);    /* allow for the EOL char etc */
  2454.         strcpy (Motd, argv[1]);
  2455.         strcat (Motd, "\n");    /* add the EOL char */
  2456.     }
  2457.     return 0;
  2458. }
  2459.  
  2460. #endif /*ALLCMD*/
  2461.  
  2462.  
  2463. /* Command history, see also pc.c - WG7J */
  2464. void
  2465. logcmd (char *cmd)
  2466. {
  2467. struct hist *new;
  2468. char *cp;
  2469.  
  2470.     if (!Maxhistory)    /* don't keep history */
  2471.         return;
  2472.  
  2473.     /* Get rid of \n; this is also done in cmdparse().
  2474.      * We HAVE to do this here, since the string is NOT null-terminated when
  2475.      * it comes from recv_mbuf()  !!!! rip() makes it nullterminated.
  2476.      */
  2477.     rip (cmd);
  2478.     cp = cmd;
  2479.     while (*cp == ' ' || *cp == '\t')
  2480.         cp++;
  2481.     if (!*cp)        /* Empty command */
  2482.         return;
  2483.  
  2484.     if (Histrysize < Maxhistory) {    /* Add new one */
  2485.         Histrysize++;
  2486.         if (!Histry) {    /* Empty list */
  2487.             /* Initialize circular linked list */
  2488.             Histry = mallocw (sizeof (struct hist));
  2489.  
  2490.             Histry->next = Histry->prev = Histry;
  2491.         } else {
  2492.             new = mallocw (sizeof (struct hist));
  2493.  
  2494.             /* Now link it in */
  2495.             Histry->next->prev = new;
  2496.             new->next = Histry->next;
  2497.             new->prev = Histry;
  2498.             Histry->next = new;
  2499.             Histry = new;
  2500.         }
  2501.     } else {
  2502.         /* Maximum number stored already, use the oldest entry */
  2503.         Histry = Histry->next;
  2504.         free (Histry->cmd);
  2505.     }
  2506.     Histry->cmd = strdup (cp);
  2507. }
  2508.  
  2509.  
  2510.  
  2511. static void
  2512. freehistory (void)
  2513. {
  2514. struct hist *h, *last;
  2515.  
  2516.     if ((h = Histry) == NULL)
  2517.         return;
  2518.     do {
  2519.         free (h->cmd);
  2520.         last = h;
  2521.         h = h->prev;
  2522.         free (last);
  2523.     } while (h != Histry);
  2524.     Histry = NULL;
  2525.     Histrysize = 0;
  2526. }
  2527.  
  2528.  
  2529.  
  2530. int
  2531. dohistory (int argc, char *argv[], void *p OPTIONAL)
  2532. {
  2533. struct hist *h;
  2534. int num;
  2535.  
  2536.     if (argc > 1) {
  2537.         Maxhistory = atoi (argv[1]);
  2538.         freehistory ();
  2539.         return 0;
  2540.     }
  2541.     tprintf ("Max recall %d\n", Maxhistory);
  2542.     if ((h = Histry) == NULL)
  2543.         return 0;
  2544.     num = 0;
  2545.     do {
  2546.         tprintf ("%.2d: %s\n", num++, h->cmd);
  2547.         h = h->prev;
  2548.     } while (h != Histry);
  2549.     return 0;
  2550. }
  2551.  
  2552.  
  2553.  
  2554. #if 0
  2555. #ifndef UNIX
  2556.  
  2557. /* This adds some additional checks to the fopen()
  2558.  * in the Borland C++ Run Time Library.
  2559.  * It fixes problem with users trying to open system devices like
  2560.  * CON, AUX etc and hang a system.
  2561.  * WG7J, 930205
  2562.  */
  2563. #undef fopen
  2564. FILE *fopen (const char * __path, const char * __mode);
  2565.  
  2566. static char *InvalidName[] =
  2567. {
  2568.     "NUL",
  2569.     "CON",
  2570.     "AUX",
  2571.     "PRN",
  2572.     "LPT1",
  2573.     "LPT2",
  2574.     "LPT3",
  2575.     "COM1",
  2576.     "COM2",
  2577.     "COM3",
  2578.     "COM4",
  2579.     "MOUSE$",
  2580.     "CLOCK$",
  2581.     NULLCHAR,
  2582. };
  2583.  
  2584.  
  2585. FILE *
  2586. newfopen (const char *filename, const char *type)
  2587. {
  2588. int i;
  2589.  
  2590.     for (i = 0; InvalidName[i] != NULLCHAR; i++)
  2591.         if (stricmp (InvalidName[i], filename) == 0)
  2592.             return NULL;
  2593.  
  2594.     return fopen (filename, type);
  2595. }
  2596.  
  2597. #endif /* UNIX */
  2598. #endif
  2599.  
  2600.  
  2601.  
  2602. /* Repeat a command - taken from 930104 KA9Q NOS
  2603.    WA3DSP 1/93
  2604. */
  2605. int
  2606. dorepeat (int argc, char *argv[], void *p)
  2607. {
  2608. int32 interval;
  2609. int ret;
  2610. struct session *sp;
  2611.  
  2612.     if (isdigit (argv[1][0])) {
  2613.         interval = atol (argv[1]);
  2614.         argc--;
  2615.         argv++;
  2616.     } else {
  2617.         interval = MSPTICK;
  2618.     }
  2619.     if ((sp = newsession (argv[1], REPEAT, 0)) == NULLSESSION) {
  2620.         tputs ("Too many sessions\n");
  2621.         return 1;
  2622.     }
  2623.     _setcursortype (_NOCURSOR);
  2624.     while (sp == Current) {
  2625.         clrscr();
  2626.         /* gotoxy seems to work better (but doen't clear screen - turn cursor off?? */
  2627.         /* gotoxy (1, 1); */
  2628.         ret = subcmd (Cmds, argc, argv, p);
  2629.         if (ret != 0 || kpause (interval) == -1)
  2630.             break;
  2631.     }
  2632.     _setcursortype (_NORMALCURSOR);
  2633.     freesession (sp);
  2634.     return 0;
  2635. }
  2636.  
  2637.  
  2638.  
  2639. int 
  2640. DisplayFile (const char *fname, int thesocket)
  2641. {
  2642. FILE *fp;
  2643. int size = 0;
  2644.  
  2645.     if ((fp = fopen (fname, READ_TEXT)) != (FILE *) 0) {
  2646.         (void) sendfile (fp, thesocket, ASCII_TYPE, 0);
  2647.         size = ftell (fp);
  2648.         (void) fclose (fp);
  2649.     }
  2650.     return (size);
  2651. }
  2652.  
  2653.  
  2654.  
  2655. #ifdef SETPSINFO
  2656. void
  2657. setprocname (buf)
  2658. char *buf;
  2659. {
  2660. register char *p, *bp, ch;
  2661. register int i;
  2662.  
  2663.     /* make ps print our process name */
  2664.     p = origargv[0];
  2665.     *p++ = '-';
  2666.  
  2667.     i = (int) strlen(buf);
  2668.     if (i > LastArgv - p - 2) {
  2669.         i = LastArgv - p - 2;
  2670.         buf[i] = '\0';
  2671.     }
  2672.     bp = buf;
  2673.     while ((ch = *bp++) != 0)
  2674.         if (ch != '\n' && ch != '\r')
  2675.             *p++ = ch;
  2676.     while (p < LastArgv)
  2677.         *p++ = ' ';
  2678. }
  2679. #endif
  2680.  
  2681.  
  2682.  
  2683. void
  2684. crash_it_already (char const *where)
  2685. {
  2686.     /* TRY a log */
  2687.     log (-1, "A 'crashprotect'-preventable restart occurred from a %s", where);
  2688.     exit (1);
  2689. }
  2690.  
  2691.  
  2692. int
  2693. shall_we_crash (void)
  2694. {
  2695.     return (CrashProtect == 0);
  2696. }
  2697.